// basic:https://www.talkenglish.com/listening/lessonlisten.aspx?ALID=100
// Intermediate:https://www.talkenglish.com/listening/lessonlisten.aspx?ALID=200
// Advanced:https://www.talkenglish.com/listening/lessonlisten.aspx?ALID=300
const puppeteer = require("puppeteer");
const fs = require("fs");
const path = require("path");

const MAX_COURSE_NUM = 100;
const URL_BASE = "https://www.talkenglish.com/listening/lessonlisten.aspx";
async function downloadLessons() {
  const levels = [
    { name: "Basic", idFrom: 100 },
    { name: "Intermediate", idFrom: 200 },
    { name: "Advanced", idFrom: 300 },
  ];
  for (let i = 0; i < levels.length; i++) {
    const level = levels[i];
    const url = `${URL_BASE}?ALID=${level.idFrom}`;
    await downloadLessonsLevel(level.name, url, level.idFrom);
  }
}
async function downloadLessonsLevel(level, url, idFrom) {
  for (let i = idFrom; i < idFrom + MAX_COURSE_NUM; i++) {
    const url = `${URL_BASE}?ALID=${i}`;
    await downloadLesson(level, i, url);
  }
}
async function downloadLesson(level, id, url) {
  // 如果url请求返回404，则跳过

  // 文件保存目录为./lessons/level/id

  // 请求url并解析获取到的html页面的元素

  // 获取页面中的.sm2-playlist-bd a 的href属性作为mp3请求路径

  // 下载mp3文件到保存目录，名称为id.mp3

  // 获取页面中#div1的元素，解析其innerHTML，其内容参考src\talkenglish\samples\div1.html
  // 转换为json保存在保存目录,名称为question.json
  // TODO:

  // 获取页面中#div3的元素，解析其innerHTML，其内容参考src\talkenglish\samples\div3.html
  // 转换为json保存在保存目录,名称为text.json

  console.log(`Downloading lesson ${level}-${id} from ${url}`);

  const browser = await puppeteer.launch();
  const page = await browser.newPage();

  try {
    // 访问页面
    const response = await page.goto(url, { waitUntil: "networkidle2" });

    // 如果响应状态不是200，跳过该课程
    if (response.status() !== 200) {
      console.log(` -> Skipped ${url} (Status: ${response.status()})`);
      await browser.close();
      return;
    }

    // 创建保存目录
    const saveDir = path.join(__dirname, "lessons", level, String(id));
    if (!fs.existsSync(saveDir)) {
      fs.mkdirSync(saveDir, { recursive: true });
    }

    // 获取MP3链接并下载
    const mp3Url = await page.$eval(".sm2-playlist-bd a", el => el.href);
    const mp3Path = path.join(saveDir, `${id}.mp3`);
    await downloadFile(mp3Url, mp3Path);

    // 获取问题部分 (#div1)
    const div1Content = await page.$eval("#div1", el => el.innerHTML);
    const questionData = parseDiv1(div1Content);
    const questionPath = path.join(saveDir, "question.json");
    fs.writeFileSync(questionPath, JSON.stringify(questionData, null, 2));

    // 获取对话文本部分 (#div3)
    const div3Content = await page.$eval("#div3", el => el.innerHTML);
    const textData = parseDiv3(div3Content);
    const textPath = path.join(saveDir, "text.json");
    fs.writeFileSync(textPath, JSON.stringify(textData, null, 2));

    console.log(` -> Saved to ${saveDir}`);
  } catch (error) {
    console.error(`Error processing ${url}:`, error.message);
  } finally {
    await browser.close();
  }
}

function parseDiv1(html) {
  // 解析问题部分
  const questions = [];
  // 先提取正确答案
  const correctAnswersMatch = html.match(/<input[^>]*name="CorrectAnswers"[^>]*value="([^"]*)"/);
  const correctAnswers = correctAnswersMatch ? correctAnswersMatch[1] : "";

  // 匹配每个问题
  const questionRegex = /(\d+)\.\s*((?:(?!<br>\s*<input).)*?)<br>((?:(?!<br>\s*\d+\.|<input[^>]*name="CorrectAnswers").)*?)<br>\s*<br>/gs;
  let questionMatch;

  while ((questionMatch = questionRegex.exec(html)) !== null) {
    const questionId = questionMatch[1];
    const questionText = questionMatch[2].trim();
    const optionsBlock = questionMatch[3];

    const options = [];
    const optionRegex = /<input[^>]*name="Question\d+"[^>]*value="([a-d])"[^>]*>\s*([^<]*?)(?=<|$)/g;
    let optionMatch;

    while ((optionMatch = optionRegex.exec(optionsBlock)) !== null) {
      options.push({
        id: optionMatch[1],
        text: optionMatch[2].trim(),
      });
    }

    questions.push({
      id: questionId,
      question: questionText,
      options: options,
    });
  }

  return {
    questions: questions,
    correctAnswers: correctAnswers,
  };
}

function parseDiv3(html) {
  // 解析对话文本部分，每一句话作为一个对象
  const cleanedHtml = html.replace(/^<br>|<br>$/g, "").trim();
  const lines = cleanedHtml.split("<br>");

  const dialog = lines.map((line, index) => {
    line = line.replace(/\\r/g,'');
    line = line.replace(/\\n/g,'');
    line = line.replace(/\\t/g,'');
    // 判断说话者是A还是B
    const speakerMatch = line.match(/^([AB]):\s*"(.*)"$/);
    if (speakerMatch) {
      return {
        id: index + 1,
        speaker: speakerMatch[1],
        text: speakerMatch[2].replace(/\r/g,'').replace(/\n/g,'').replace(/\t/g,''),
      };
    }
    // 处理没有明确说话者的行
    return {
      id: index + 1,
      speaker: "",
      text: line.replace(/\r/g,'').replace(/\n/g,'').replace(/\t/g,''),
    };
  });
  console.log(dialog);
  for (let i = dialog.length - 1; i >= 0; i--) {
    if (dialog[i].text === "") {
      // 移除dialog[i]
      dialog.splice(i, 1);
    }
  }

  return {
    dialog: dialog,
  };
}

async function downloadFile(url, output) {
  // 如果目标文件存在，且大小大于0，则跳过
  if (fs.existsSync(output) && fs.statSync(output).size > 0) {
    console.log(` -> Skipped ${url}`);
    return;
  }
  const response = await fetch(url);
  const buffer = await response.arrayBuffer();
  fs.writeFileSync(output, Buffer.from(buffer));
  console.log(`    Downloaded ${url}`);
  console.log(`    --> to ${output}`);
}

async function main() {
  await downloadLessons();
}

main();
